package com.emmmya.ocs.common.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.thymeleaf.util.StringUtils;

import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;

/**
 * 二维码、条形码工具类
 */
@Slf4j
public class QRCodeUtil {
    /**
     * CODE_WIDTH：二维码宽度，单位像素
     * CODE_HEIGHT：二维码高度，单位像素
     * FRONT_COLOR：二维码前景色，0x000000 表示黑色
     * BACKGROUND_COLOR：二维码背景色，0xFFFFFF 表示白色
     * 演示用 16 进制表示，和前端页面 CSS 的取色是一样的，注意前后景颜色应该对比明显，如常见的黑白
     */
    private static final int CODE_WIDTH = 600;
    private static final int CODE_HEIGHT = 600;
    private static final int FRONT_COLOR = 0x000000;
    private static final int BACKGROUND_COLOR = 0xFFFFFF;

    public static void main(String[] args) {
//        String personText =
//                "李占占\t2104010592\t焊点检查\t重点工序\n" +
//                "胡亚熊\t2207100237\t焊点检查\t重点工序\n" +
//                "刘二林\t2109010145\t成品外观检查\t重点工序\n" +
//                "王冬秀\t2203140054\t助拉\t重点工序\n" +
//                "朱正会\t2203070287\t成品外观检查\t重点工序\n" +
//                "兰小云\t2203020274\t打包\t重点工序\n" +
//                "龚维婷\t2206170171\t电芯定位\t普通工序\n" +
//                "刘江伟\t2206200096\tPCM定位\t普通工序\n" +
//                "李善祥\t2206050007\t包商标\t普通工序\n" +
//                "倪璐璐\t2206200079\tNTC点胶\t普通工序\n" +
//                "卢艳雪\tL2204100040\t装支架\t普通工序\n" +
//                "龚维婷\t2206170171\t上料装电芯，PCB板\t普通工序\n" +
//                "刘江伟\t2206200096\t上料装电芯，PCB板\t普通工序\n" +
//                "李善祥\t2206050007\t装胶框，打导热胶\t普通工序\n" +
//                "倪璐璐\t2206200079\t装上盖\t普通工序\n" +
//                "卢艳雪\tL2204100040\t包商标\t普通工序\n"+
//                "祝桃美\t2206180031\t上料装电芯，PCB板\t普通岗位\n" +
//                "余小雪\t2202220292\t贴胶纸\t普通岗位\n" +
//                "梁大顺\t2206040017\t上料装电芯，PCB板\t普通岗位\n" +
//                "林灯凤\tL220240001\t焊点检查\t关键岗位\n" +
//                "吴英学\tL2204110032\t贴胶纸\t普通岗位\n" +
//                "马聪聪\t2207130170\t装胶框\t普通岗位\n" +
//                "张启平\t2207130185\t装上盖\t普通岗位\n" +
//                "吴维\t2202230294\t贴商标\t普通岗位\n" +
//                "张俊艳\t2203010406\t包商标\t普通岗位\n" +
//                "谭军辉\t2203010420\t贴条码和条码绑定\t普通岗位\n" +
//                "程晓燕\t2207130182\t贴商标\t普通岗位\n" +
//                "付帅豪\t2203140080\t功能测试\t关键岗位\n" +
//                "徐黎辉\t2207130176\t功能测试\t关键岗位\n" +
//                "宁乐伟\t2203010402\t尺寸检查\t关键岗位\n" +
//                "王彬慧\t2206150096\t成品外观检查\t关键岗位\n" +
//                "李朋朋\t2203010461\t打包\t关键岗位\n"+
//                "盛玉华\t2206080043\t上料装电芯，PCB板\t普通岗位\n" +
//                "梁峰华\t2207130183\t焊点检查\t关键岗位\n" +
//                "王强\t2202240281\t包胶纸\t普通岗位\n" +
//                "王昆鹏\t2206020046\t包胶纸\t普通岗位\n" +
//                "马灵恩\t2206200074\t连接器检查\t关键岗位\n" +
//                "关德照\t2206010203\t尺寸检查\t关键岗位\n" +
//                "罗雯雯\t2207070088\t成品外观检查\t关键岗位\n" +
//                "温国云生\t2104220111\t打包\t关键岗位\n";
//
//        String[] split = personText.split("\n");
//        ArrayList<PersonJobBaseQREntity> personJobQREntities = new ArrayList<>();
//        for (String s : split) {
//            if(s!=null && !s.equals("")){
//                String[] split1 = s.split("\t");
//                PersonJobBaseQREntity item = new PersonJobBaseQREntity();
//                item.setEmployeeName(split1[0]);
//                item.setEmployeeNumber(split1[1]);
//                List<String> positions = Arrays.stream(split1[2].split("，")).collect(Collectors.toList());
//                item.setPosition(positions);
//                item.setRemarks(split1[3]);
//                item.setQrCodeFlag("员工技能");
//                personJobQREntities.add(item);
//            }
//
//        }
//
//        for (PersonJobBaseQREntity personJobQREntity : personJobQREntities) {
//            String obj = JSON.toJSONString(personJobQREntity);
//            createCodeToFile(obj, new File("D:\\Users\\2003030042\\Desktop\\员工技能"), personJobQREntity.getEmployeeNumber()+"-"+personJobQREntity.getEmployeeName()+".png");
//
//        }
//
//
//        String sopText =
//                "LX-C-3F-C04\t001\t电芯分选&极耳裁切\t电芯分选\t关键岗位\n" +
//                "LX-C-3F-C04\t012\t装PCM板\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C04\t013\t电芯组装\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C04\t003\t半成品外观检查\t焊点检查\t关键岗位\n" +
//                "LX-C-3F-C04\t014\t电芯组装支架&打导热胶\t装胶框，打导热胶\t普通岗位\n" +
//                "LX-C-3F-C04\t015\t装盖板\t装上盖\t普通岗位\n" +
//                "LX-C-3F-C04\t016\t半成品入贴标载具\t电芯组转载\t普通岗位\n" +
//                "LX-C-3F-C04\t017\t包正标\t贴商标\t普通岗位\n" +
//                "LX-C-3F-C04\t004\t半成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C04\t005\t老化测试\t活化\t关键岗位\n" +
//                "LX-C-3F-C04\t006\t成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C04\t007\t成品厚度尺寸检查\t尺寸检查\t关键岗位\n" +
//                "LX-C-3F-C04\t008\t成品外观检查\t成品外观检查\t关键岗位\n" +
//                "LX-C-3F-C04\t011\t扫描&称重&打包\t打包\t关键岗位\n" +
//                "LX-C-3F-C04\t009\t焊接JP点\t焊锡\t关键岗位\n" +
//                "LX-C-3F-C04\t018\t贴成品条码\t贴商标\t普通岗位\n" +
//                "LX-C-3F-C04\t010\t连接器外观检查\t连接器外观检查\t关键岗位\n"+
//                "LX-C-3F-C05\t001\t电芯分选&极耳裁切\t电芯分选\t关键岗位\n" +
//                "LX-C-3F-C05\t019\t贴底部钢片\t贴钢片\t普通岗位\n" +
//                "LX-C-3F-C05\t020\t贴电芯泡棉\t贴泡棉\t普通岗位\n" +
//                "LX-C-3F-C05\t021\t电芯&PCM定位\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C05\t003\t半成品外观检查\t焊点检查\t关键岗位\n" +
//                "LX-C-3F-C05\t022\t贴正面PC片&捋NTC引线\t贴胶纸\t普通岗位\n" +
//                "LX-C-3F-C05\t023\tNTC点胶&贴高温胶纸\tNTC点胶，贴胶纸\t普通岗位\n" +
//                "LX-C-3F-C05\t024\t贴反面PC片\t贴胶纸\t普通岗位\n" +
//                "LX-C-3F-C05\t025\t电芯入胶框&扣上盖\t装胶框，装上盖\t普通岗位\n" +
//                "LX-C-3F-C05\t012\t扣钢壳\t扣钢壳\t关键岗位\n" +
//                "LX-C-3F-C05\t024\t半成品下料\t半成品下料\t普通岗位\n" +
//                "LX-C-3F-C05\t005\t老化测试\t活化\t关键岗位\n" +
//                "LX-C-3F-C05\t006\t成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C05\t007\t成品厚度尺寸检查\t尺寸检查\t关键岗位\n" +
//                "LX-C-3F-C05\t008\t成品外观检查\t成品外观检查\t关键岗位\n" +
//                "LX-C-3F-C05\t011\t扫描&称重&打包\t打包\t关键岗位\n"+
//                "LX-C-3F-C18\t027\t电芯组装\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C18\t028\t贴双面胶\t贴胶纸\t普通岗位\n" +
//                "LX-C-3F-C18\t021\t电芯&PCM定位\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C18\t003\t半成品外观检查\t焊点检查\t关键岗位\n" +
//                "LX-C-3F-C18\t023\tNTC点胶&贴高温胶纸\tNTC点胶，贴胶纸\t普通岗位\n" +
//                "LX-C-3F-C18\t029\t电芯组入支架\t装胶框\t普通岗位\n" +
//                "LX-C-3F-C18\t015\t装盖板\t装上盖\t普通岗位\n" +
//                "LX-C-3F-C18\t030\t贴正面商标\t贴商标\t普通岗位\n" +
//                "LX-C-3F-C18\t017\t包商标\t包商标\t普通岗位\n" +
//                "LX-C-3F-C18\t018\t贴成品条码\t贴条码和条码绑定\t普通岗位\n" +
//                "LX-C-3F-C18\t031\t贴背面商标\t贴商标\t普通岗位\n" +
//                "LX-C-3F-C18\t004\t半成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C18\t006\t成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C18\t007\t成品厚度尺寸检查\t尺寸检查\t关键岗位\n" +
//                "LX-C-3F-C18\t008\t成品外观检查\t成品外观检查\t关键岗位\n" +
//                "LX-C-3F-C18\t011\t扫描&称重&打包\t打包\t关键岗位\n"+
//                "LX-C-3F-C11\t031\t电芯、PCM上料\t上料装电芯，PCB板\t普通岗位\n" +
//                "LX-C-3F-C11\t003\t半成品外观检查\t焊点检查\t关键岗位\n" +
//                "LX-C-3F-C11\t017\t包商标\t包商标\t普通岗位\n" +
//                "LX-C-3F-C11\t006\t成品功能测试\t功能测试\t关键岗位\n" +
//                "LX-C-3F-C11\t010\t连接器外观检查\t连接器外观检查\t关键岗位\n" +
//                "LX-C-3F-C11\t007\t成品厚度尺寸检查\t尺寸检查\t关键岗位\n" +
//                "LX-C-3F-C11\t008\t成品外观检查\t成品外观检查\t关键岗位\n" +
//                "LX-C-3F-C11\t011\t扫描&称重&打包\t打包\t关键岗位\n";
//        String[] split2 = sopText.split("\n");
//        ArrayList<SopSkillBaseQREntity> sopSkillQREntityArrayList = new ArrayList<>();
//        for (String s : split2) {
//            if(s!=null && !s.equals("")){
//                String[] split1 = s.split("\t");
//                SopSkillBaseQREntity sopEntity = new SopSkillBaseQREntity();
//                //sopEntity.setProductionLine(split1[0]);
//                sopEntity.setProcedureNumber(split1[1]);
//                sopEntity.setProcedureName(split1[2]);
////                ArrayList<String> skills = new ArrayList<>();
//                List<String> skills = Arrays.stream(split1[3].split("，")).collect(Collectors.toList());
////                skills.add(split1[3]);
//                sopEntity.setSkills(skills);
//                sopEntity.setRemarks(split1[4]);
//                sopEntity.setQrCodeFlag("SOP技能");
//                sopSkillQREntityArrayList.add(sopEntity);
//
//            }
//
//        }
//
//        for (SopSkillBaseQREntity sopEntity : sopSkillQREntityArrayList) {
//            String sopObj = JSON.toJSONString(sopEntity);
//            createCodeToFile(sopObj, new File("D:\\Users\\2003030042\\Desktop\\SOP岗位技能"), sopEntity.getProcedureNumber()+"-"+sopEntity.getProcedureName()+".png");
//        }
//        String skillsStr = "测试，测试2    , 测试3";
//        skillsStr = skillsStr.replace("，",",");
//        System.out.println(Arrays.stream(skillsStr.split(",")).collect(Collectors.toList()));
        createCodeToFile("http://10.161.200.49/assets/getFile/f286b38e6b044239b28e46749cf9a5ab.apk",null,null,"徐建真-2209140003");

//        System.out.println(Long.parseLong(""));


    }
    /**
     * 生成二维码 并 保存为图片
     */

    /**
     * @param codeContent        :二维码参数内容，如果是一个网页地址，如 https://www.baidu.com/ 则 微信扫一扫会直接进入此地址
     *                           如果是一些参数，如 1541656080837，则微信扫一扫会直接回显这些参数值
     * @param codeImgFileSaveDir :二维码图片保存的目录,如 D:/codes
     * @param fileName           :二维码图片文件名称，带格式,如 123.png
     */
    public static void createCodeToFile(String codeContent, File codeImgFileSaveDir, String fileName) {
        try {
            /** 参数检验*/
            if (codeContent == null || "".equals(codeContent)) {
                System.out.println("二维码内容为空，不进行操作...");
                return;
            }
            codeContent = codeContent.trim();
            if (codeImgFileSaveDir == null || codeImgFileSaveDir.isFile()) {
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
                //System.out.println("二维码图片存在目录为空，默认放在桌面...");
            }
            if (!codeImgFileSaveDir.exists()) {
                codeImgFileSaveDir.mkdirs();
                //System.out.println("二维码图片存在目录不存在，开始创建...");
            }
            if (fileName == null || "".equals(fileName)) {
                fileName = new Date().getTime() + ".png";
                //System.out.println("二维码图片文件名为空，随机生成 png 格式图片...");
            }
            /**com.google.zxing.EncodeHintType：编码提示类型,枚举类型
             * EncodeHintType.CHARACTER_SET：设置字符编码类型
             * EncodeHintType.ERROR_CORRECTION：设置误差校正
             *      ErrorCorrectionLevel：误差校正等级，L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
             *      不设置时，默认为 L 等级，等级不一样，生成的图案不同，但扫描的结果是一样的
             * EncodeHintType.MARGIN：设置二维码边距，单位像素，值越小，二维码距离四周越近
             * */
            Map<EncodeHintType, Object> hints = new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 1);

            /**
             * MultiFormatWriter:多格式写入，这是一个工厂类，里面重载了两个 encode 方法，用于写入条形码或二维码
             *      encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
             *      contents:条形码/二维码内容
             *      format：编码类型，如 条形码，二维码 等
             *      width：码的宽度
             *      height：码的高度
             *      hints：码内容的编码类型
             * BarcodeFormat：枚举该程序包已知的条形码格式，即创建何种码，如 1 维的条形码，2 维的二维码 等
             * BitMatrix：位(比特)矩阵或叫2D矩阵，也就是需要的二维码
             */
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);

            /**java.awt.image.BufferedImage：具有图像数据的可访问缓冲图像，实现了 RenderedImage 接口
             * BitMatrix 的 get(int x, int y) 获取比特矩阵内容，指定位置有值，则返回true，将其设置为前景色，否则设置为背景色
             * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
             *      x：像素位置的横坐标，即列
             *      y：像素位置的纵坐标，即行
             *      rgb：像素的值，采用 16 进制,如 0xFFFFFF 白色
             */
            BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
            for (int x = 0; x < CODE_WIDTH; x++) {
                for (int y = 0; y < CODE_HEIGHT; y++) {
                    bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
                }
            }

            /**javax.imageio.ImageIO java 扩展的图像IO
             * write(RenderedImage im,String formatName,File output)
             *      im：待写入的图像
             *      formatName：图像写入的格式
             *      output：写入的图像文件，文件不存在时会自动创建
             *
             * 即将保存的二维码图片文件*/
            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(bufferedImage, "png", codeImgFile);

            log.warn("二维码图片生成成功：" + codeImgFile.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param codeContent        :二维码参数内容，如果是一个网页地址，如 https://www.baidu.com/ 则 微信扫一扫会直接进入此地址
     *                           如果是一些参数，如 1541656080837，则微信扫一扫会直接回显这些参数值
     * @param codeImgFileSaveDir :二维码图片保存的目录,如 D:/codes
     * @param fileName           :二维码图片文件名称，带格式,如 123.png
     */
    public static void createCodeToFile(String codeContent, File codeImgFileSaveDir, String fileName,String footer) {
        try {
            /** 参数检验*/
            if (codeContent == null || "".equals(codeContent)) {
                log.warn("二维码内容为空，不进行操作...");
                return;
            }
            codeContent = codeContent.trim();
            if (codeImgFileSaveDir == null || codeImgFileSaveDir.isFile()) {
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
                log.warn("二维码图片存在目录为空，默认放在桌面...");
            }
            if (!codeImgFileSaveDir.exists()) {
                boolean mkdirs = codeImgFileSaveDir.mkdirs();
                log.warn("二维码图片存在目录不存在，开始创建...创建结果："+mkdirs);
            }
            if (fileName == null || "".equals(fileName)) {
                fileName = new Date().getTime() + ".png";
                //System.out.println("二维码图片文件名为空，随机生成 png 格式图片...");
            }
            /**com.google.zxing.EncodeHintType：编码提示类型,枚举类型
             * EncodeHintType.CHARACTER_SET：设置字符编码类型
             * EncodeHintType.ERROR_CORRECTION：设置误差校正
             *      ErrorCorrectionLevel：误差校正等级，L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
             *      不设置时，默认为 L 等级，等级不一样，生成的图案不同，但扫描的结果是一样的
             * EncodeHintType.MARGIN：设置二维码边距，单位像素，值越小，二维码距离四周越近
             * */
            Map<EncodeHintType, Object> hints = new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 1);

            /**
             * MultiFormatWriter:多格式写入，这是一个工厂类，里面重载了两个 encode 方法，用于写入条形码或二维码
             *      encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
             *      contents:条形码/二维码内容
             *      format：编码类型，如 条形码，二维码 等
             *      width：码的宽度
             *      height：码的高度
             *      hints：码内容的编码类型
             * BarcodeFormat：枚举该程序包已知的条形码格式，即创建何种码，如 1 维的条形码，2 维的二维码 等
             * BitMatrix：位(比特)矩阵或叫2D矩阵，也就是需要的二维码
             */
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);

            /**java.awt.image.BufferedImage：具有图像数据的可访问缓冲图像，实现了 RenderedImage 接口
             * BitMatrix 的 get(int x, int y) 获取比特矩阵内容，指定位置有值，则返回true，将其设置为前景色，否则设置为背景色
             * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
             *      x：像素位置的横坐标，即列
             *      y：像素位置的纵坐标，即行
             *      rgb：像素的值，采用 16 进制,如 0xFFFFFF 白色
             */
            BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, StringUtils.isEmpty(footer) ? CODE_HEIGHT : CODE_HEIGHT + 100, BufferedImage.TYPE_INT_BGR);
            for (int x = 0; x < CODE_WIDTH; x++) {
                for (int y = 0; y < CODE_HEIGHT; y++) {
                    bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
                }
            }
            if(!StringUtils.isEmpty(footer)) {
                int cnLength = length(footer);
                //其它非中文字符，两个字符算一个
                int otherLenth = footer.length() - cnLength;
                int finalLength = cnLength + (otherLenth/2) ;
                Graphics2D typeLeft = bufferedImage.createGraphics();
                // 设置字体颜色
                typeLeft.setColor(Color.white);
                // 设置字体
                Font footerFont = new Font("黑体", Font.BOLD, 40);
                typeLeft.setFont(footerFont);
                typeLeft.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
                int startX = (CODE_WIDTH - (footerFont.getSize() * finalLength)) / 2;
                int height = CODE_HEIGHT + 68;
                typeLeft.drawString(footer, startX, height);
            }

            /**javax.imageio.ImageIO java 扩展的图像IO
             * write(RenderedImage im,String formatName,File output)
             *      im：待写入的图像
             *      formatName：图像写入的格式
             *      output：写入的图像文件，文件不存在时会自动创建
             *
             * 即将保存的二维码图片文件*/
            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(bufferedImage, "png", codeImgFile);

            log.warn("二维码图片生成成功：" + codeImgFile.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //判断汉字的个数
    public static int length(String value) {
        int valueLength = 0;
        String chinese = "[\u0391-\uFFE5]";
        /* 获取字段值的长度，如果含中文字符，则每个中文字符长度为2，否则为1 */
        for (int i = 0; i < value.length(); i++) {
            /* 获取一个字符 */
            String temp = value.substring(i, i + 1);
            /* 判断是否为中文字符 */
            if (temp.matches(chinese)) {
                /* 中文字符长度为2 */
                valueLength += 1;
            }
        }
        return valueLength;

    }
}